
<!DOCTYPE html>
<html lang="en" data-figures="" class="page">
  <head>
<title>SpringMVC | Alexzshl</title>
<meta charset="utf-8">
<meta name="generator" content="Hugo 0.80.0" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta property="og:locale" content="en" />

<meta property="og:type" content="article">
<meta name="description" content="Article description.">
<meta name="twitter:card" content="summary" />
<meta name="twitter:creator" content="">
<meta name="twitter:title" content="SpringMVC" />
<meta property="og:url" content="https://alexzshl.gitee.io/blog/post/springmvc/" />
<meta property="og:title" content="SpringMVC" />
<meta property="og:description" content="Article description." />
<meta property="og:image" content="https://alexzshl.gitee.io/blog/" />
<link rel="apple-touch-icon" sizes="180x180" href='https://alexzshl.gitee.io/blog/icons/apple-touch-icon.png'>
<link rel="icon" type="image/png" sizes="32x32" href='https://alexzshl.gitee.io/blog/icons/favicon-32x32.png'>
<link rel="manifest" href='https://alexzshl.gitee.io/blog/icons/site.webmanifest'>
<link rel="mask-icon" href='https://alexzshl.gitee.io/blog/safari-pinned-tab.svg' color="#002538">
<meta name="msapplication-TileColor" content="#002538">
<meta name="theme-color" content="#002538">

<link rel="canonical" href="https://alexzshl.gitee.io/blog/post/springmvc/">

    

    
    
    <link rel="preload" href="https://alexzshl.gitee.io/blog/css/styles.782bf96a82b3cc5b3cee4c47a42cc81321f16960a6d41fab3277c4abe047bc7ae044ea1bb7ae4d237c12baa0143e02f95969e5e8b6e68d9dcfd14158cfa244ac.css" integrity = "sha512-eCv5aoKzzFs87kxHpCzIEyHxaWCm1B&#43;rMnfEq&#43;BHvHrgROobt65NI3wSuqAUPgL5WWnl6LbmjZ3P0UFYz6JErA==" as="style" crossorigin="anonymous">
    <link rel="preload" href="https://alexzshl.gitee.io/blog/js/bundle.min.16ce52f0798f54d65cefb0a0fc9228cf99e0b73de57f8a1545fe14259265bf79ba12fe15afd2fd75d5f0bff8f416e8ca8c5c3458f87e014cbfbed8ccfdaee327.js" as="script" integrity=
    "sha512-Fs5S8HmPVNZc77Cg/JIoz5ngtz3lf4oVRf4UJZJlv3m6Ev4Vr9L9ddXwv/j0FujKjFw0WPh&#43;AUy/vtjM/a7jJw==" crossorigin="anonymous">

    
    <link rel="stylesheet" type="text/css" href="https://alexzshl.gitee.io/blog/css/styles.782bf96a82b3cc5b3cee4c47a42cc81321f16960a6d41fab3277c4abe047bc7ae044ea1bb7ae4d237c12baa0143e02f95969e5e8b6e68d9dcfd14158cfa244ac.css" integrity="sha512-eCv5aoKzzFs87kxHpCzIEyHxaWCm1B&#43;rMnfEq&#43;BHvHrgROobt65NI3wSuqAUPgL5WWnl6LbmjZ3P0UFYz6JErA==" crossorigin="anonymous">
    
  </head>
  
  
    
  
  <body data-code="100" data-lines="false" id="documentTop">

<header class="nav_header" >
  <nav class="nav">
    <a href='https://alexzshl.gitee.io/blog/' class="nav_brand nav_item">
        Alexzshl
      <div class="nav_close">
        <div>
          <svg class="icon">
  <use xlink:href="#open-menu"></use>
</svg>
          <svg class="icon">
  <use xlink:href="#closeme"></use>
</svg>
        </div>
      </div>
    </a>
    <div class='nav_body nav_body_'>
      
      
      
        

      
<div class='follow'>
<div class="color_mode">
  <input type="checkbox" class="color_choice" id="mode">
</div>

</div>

    </div>
  </nav>
</header>

    <main>
  
<div class="grid-inverse wrap content">
  <article class="post_content">
    <h1 class="post_title">SpringMVC</h1><div class="post_meta">
  
    <svg class="icon">
  <use xlink:href="#calendar"></use>
</svg>
    <span class="post_date">
      Oct 6, 2020</span>
      <a href='https://alexzshl.gitee.io/blog/tags/web' class="post_tag button button_translucent">web
      </a>
      <a href='https://alexzshl.gitee.io/blog/tags/springmvc' class="post_tag button button_translucent">springmvc
      </a>
</div>

    
  <div class="post_share">
    Share on:
    <a href="https://twitter.com/intent/tweet?text=SpringMVC&url=https%3a%2f%2falexzshl.gitee.io%2fblog%2fpost%2fspringmvc%2f&tw_p=tweetbutton" class="twitter" title="Share on Twitter" target="_blank" rel="nofollow">
      <svg class="icon">
  <use xlink:href="#twitter"></use>
</svg>
    </a>
    <a href="https://www.facebook.com/sharer.php?u=https%3a%2f%2falexzshl.gitee.io%2fblog%2fpost%2fspringmvc%2f&t=SpringMVC" class="facebook" title="Share on Facebook" target="_blank" rel="nofollow">
      <svg class="icon">
  <use xlink:href="#facebook"></use>
</svg>
    </a>
    <a href="#linkedinshare" id = "linkedinshare" class="linkedin" title="Share on LinkedIn" rel="nofollow">
      <svg class="icon">
  <use xlink:href="#linkedin"></use>
</svg>
    </a>
    <a href="https://alexzshl.gitee.io/blog/post/springmvc/" title="Copy Link" class="link link_yank">
      <svg class="icon">
  <use xlink:href="#copy"></use>
</svg>
    </a>
  </div>

    
    
    <h2>Overview</h2>
    <nav id="TableOfContents">
  <ul>
    <li><a href="#简介">简介</a></li>
    <li><a href="#springmvc">SpringMVC</a></li>
    <li><a href="#pomxml-示例">pom.xml 示例</a></li>
    <li><a href="#webxml-示例">web.xml 示例</a></li>
    <li><a href="#applicatianxml-示例">applicatian.xml 示例</a></li>
    <li><a href="#注解">注解</a></li>
    <li><a href="#rest-风格的请求">Rest 风格的请求</a></li>
    <li><a href="#使用-pojo">使用 Pojo</a></li>
    <li><a href="#使用-servlet-api">使用 servlet api</a></li>
    <li><a href="#model-view">Model View</a>
      <ul>
        <li><a href="#返回值类型-modelandview-打包model和view">返回值类型 ModelAndView 打包model和view</a></li>
        <li><a href="#通过形参-map-类型来处理model">通过形参 Map 类型来处理model</a></li>
      </ul>
    </li>
    <li><a href="#结果跳转方式">结果跳转方式</a></li>
    <li><a href="#视图和视图解析器">视图和视图解析器</a></li>
    <li><a href="#json">JSON</a>
      <ul>
        <li><a href="#restcontroller">RestController</a></li>
      </ul>
    </li>
    <li><a href="#拦截器">拦截器</a>
      <ul>
        <li><a href="#modelattribute">@ModelAttribute</a></li>
        <li><a href="#自定义拦截器">自定义拦截器</a></li>
      </ul>
    </li>
    <li><a href="#文件上传">文件上传</a></li>
    <li><a href="#国际化-i18n">国际化 i18n</a>
      <ul>
        <li><a href="#通过请求参数来切换local">通过请求参数来切换local</a></li>
      </ul>
    </li>
    <li><a href="#数据校验">数据校验</a>
      <ul>
        <li><a href="#jsr303-规范">JSR303 规范</a></li>
        <li><a href="#hibernate-validator">Hibernate Validator</a></li>
        <li><a href="#spring-mvc-数据校验">Spring MVC 数据校验</a></li>
      </ul>
    </li>
    <li><a href="#json-and-ajax">JSON and AJAX</a></li>
    <li><a href="#拦截器-1">拦截器</a>
      <ul>
        <li><a href="#自定义拦截器-1">自定义拦截器</a></li>
        <li><a href="#生命周期">生命周期</a></li>
        <li><a href="#拦截器顺序">拦截器顺序</a></li>
      </ul>
    </li>
    <li><a href="#异常处理">异常处理</a>
      <ul>
        <li><a href="#responsestatusexceptionresolver">ResponseStatusExceptionResolver</a></li>
        <li><a href="#defaulthandlerexceptionresolver">DefaultHandlerExceptionResolver</a></li>
        <li><a href="#simplemappingexceptionresolver">SimpleMappingExceptionResolver</a></li>
      </ul>
    </li>
    <li><a href="#springmvc-运行流程">SpringMVC 运行流程</a></li>
    <li><a href="#spring-整合-springmvc">Spring 整合 SpringMVC</a>
      <ul>
        <li><a href="#整合ssm">整合SSM</a></li>
      </ul>
    </li>
  </ul>
</nav>
    <h2 id="简介">简介</h2>
<p>view 层(展现层) MVC设计理念的一个Web实现框架,同类对比有struts2</p>
<p>关键点:MVC注解, POJO</p>
<p>支持 REST 风格</p>
<p>松散耦合, 可插拔</p>
<h2 id="springmvc">SpringMVC</h2>
<p>spring-web, spring-webmvc</p>
<p>spring-webmvc 是一个高层模块,如果使用mvn只需要导入此一项依赖即可,其子依赖项包括spring核心库和sping-web</p>
<p>spring-webmvc 依赖库</p>
<ol>
<li>core</li>
<li>beans</li>
<li>context</li>
<li>expression</li>
<li>aop</li>
<li>web</li>
</ol>
<h2 id="pomxml-示例">pom.xml 示例</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml"><span style="color:#75715e">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span>
<span style="color:#f92672">&lt;project</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#34;http://maven.apache.org/POM/4.0.0&#34;</span>
         <span style="color:#a6e22e">xmlns:xsi=</span><span style="color:#e6db74">&#34;http://www.w3.org/2001/XMLSchema-instance&#34;</span>
         <span style="color:#a6e22e">xsi:schemaLocation=</span><span style="color:#e6db74">&#34;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&#34;</span><span style="color:#f92672">&gt;</span>
    <span style="color:#f92672">&lt;modelVersion&gt;</span>4.0.0<span style="color:#f92672">&lt;/modelVersion&gt;</span>

    <span style="color:#f92672">&lt;groupId&gt;</span>com.alex<span style="color:#f92672">&lt;/groupId&gt;</span>
    <span style="color:#f92672">&lt;artifactId&gt;</span>91-example-01<span style="color:#f92672">&lt;/artifactId&gt;</span>
    <span style="color:#f92672">&lt;version&gt;</span>1.0-SNAPSHOT<span style="color:#f92672">&lt;/version&gt;</span>
    <span style="color:#f92672">&lt;packaging&gt;</span>war<span style="color:#f92672">&lt;/packaging&gt;</span>

    <span style="color:#f92672">&lt;dependencies&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.springframework<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>spring-webmvc<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>5.2.12.RELEASE<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.springframework<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>spring-jdbc<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>5.2.12.RELEASE<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.aspectj<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>aspectjweaver<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>1.9.6<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>mysql<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>mysql-connector-java<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>5.1.47<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.mybatis<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>mybatis<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>3.5.6<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.mybatis<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>mybatis-spring<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>2.0.6<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>javax.servlet<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>javax.servlet-api<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>3.1.0<span style="color:#f92672">&lt;/version&gt;</span>
            <span style="color:#f92672">&lt;scope&gt;</span>provided<span style="color:#f92672">&lt;/scope&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>javax.servlet.jsp<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>javax.servlet.jsp-api<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>2.2.1<span style="color:#f92672">&lt;/version&gt;</span>
            <span style="color:#f92672">&lt;scope&gt;</span>provided<span style="color:#f92672">&lt;/scope&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>javax.servlet<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>jstl<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>1.2<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>

        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>junit<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>junit<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>4.12<span style="color:#f92672">&lt;/version&gt;</span>
            <span style="color:#f92672">&lt;scope&gt;</span>test<span style="color:#f92672">&lt;/scope&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.projectlombok<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>lombok<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>1.18.16<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
    <span style="color:#f92672">&lt;/dependencies&gt;</span>
<span style="color:#f92672">&lt;/project&gt;</span>

</code></pre></div><h2 id="webxml-示例">web.xml 示例</h2>
<p>关于/ 和 /*</p>
<p>/ 不会匹配去匹配jsp文件请求,而是由tomcat直接返回</p>
<p>/* 会匹配所有的请求,一般用在过滤器等地方,例如用来对编码进行处理等</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml"><span style="color:#75715e">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span>
<span style="color:#f92672">&lt;web-app</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#34;http://xmlns.jcp.org/xml/ns/javaee&#34;</span>
         <span style="color:#a6e22e">xmlns:xsi=</span><span style="color:#e6db74">&#34;http://www.w3.org/2001/XMLSchema-instance&#34;</span>
         <span style="color:#a6e22e">xsi:schemaLocation=</span><span style="color:#e6db74">&#34;http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd&#34;</span>
             <span style="color:#a6e22e">version=</span><span style="color:#e6db74">&#34;4.0&#34;</span><span style="color:#f92672">&gt;</span>

    <span style="color:#f92672">&lt;listener&gt;</span>
        <span style="color:#f92672">&lt;listener-class&gt;</span>org.springframework.web.context.ContextLoaderListener<span style="color:#f92672">&lt;/listener-class&gt;</span>
    <span style="color:#f92672">&lt;/listener&gt;</span>

    <span style="color:#f92672">&lt;servlet&gt;</span>
        <span style="color:#f92672">&lt;servlet-name&gt;</span>dispatcher<span style="color:#f92672">&lt;/servlet-name&gt;</span>
        <span style="color:#f92672">&lt;servlet-class&gt;</span>org.springframework.web.servlet.DispatcherServlet<span style="color:#f92672">&lt;/servlet-class&gt;</span>
        <span style="color:#f92672">&lt;init-param&gt;</span>
            <span style="color:#f92672">&lt;param-name&gt;</span>contextConfigLocation<span style="color:#f92672">&lt;/param-name&gt;</span>
            <span style="color:#f92672">&lt;param-value&gt;</span>/WEB-INF/applicationContext.xml<span style="color:#f92672">&lt;/param-value&gt;</span>
        <span style="color:#f92672">&lt;/init-param&gt;</span>
        <span style="color:#f92672">&lt;load-on-startup&gt;</span>1<span style="color:#f92672">&lt;/load-on-startup&gt;</span>
    <span style="color:#f92672">&lt;/servlet&gt;</span>

    <span style="color:#f92672">&lt;servlet-mapping&gt;</span>
        <span style="color:#f92672">&lt;servlet-name&gt;</span>dispatcher<span style="color:#f92672">&lt;/servlet-name&gt;</span>
        <span style="color:#f92672">&lt;url-pattern&gt;</span>/<span style="color:#f92672">&lt;/url-pattern&gt;</span>
    <span style="color:#f92672">&lt;/servlet-mapping&gt;</span>

<span style="color:#f92672">&lt;/web-app&gt;</span>
</code></pre></div><h2 id="applicatianxml-示例">applicatian.xml 示例</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml"><span style="color:#75715e">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span>
<span style="color:#f92672">&lt;beans</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#34;http://www.springframework.org/schema/beans&#34;</span>
       <span style="color:#a6e22e">xmlns:xsi=</span><span style="color:#e6db74">&#34;http://www.w3.org/2001/XMLSchema-instance&#34;</span>
       <span style="color:#a6e22e">xmlns:context=</span><span style="color:#e6db74">&#34;http://www.springframework.org/schema/context&#34;</span>
       <span style="color:#a6e22e">xsi:schemaLocation=</span><span style="color:#e6db74">&#34;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd&#34;</span><span style="color:#f92672">&gt;</span>

    <span style="color:#f92672">&lt;context:component-scan</span> <span style="color:#a6e22e">base-package=</span><span style="color:#e6db74">&#34;com.alex.handlers&#34;</span><span style="color:#f92672">&gt;&lt;/context:component-scan&gt;</span>

    <span style="color:#f92672">&lt;bean</span> <span style="color:#a6e22e">class=</span><span style="color:#e6db74">&#34;org.springframework.web.servlet.view.InternalResourceViewResolver&#34;</span><span style="color:#f92672">&gt;</span>
        <span style="color:#f92672">&lt;property</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;prefix&#34;</span> <span style="color:#a6e22e">value=</span><span style="color:#e6db74">&#34;/WEB-INF/views/&#34;</span><span style="color:#f92672">&gt;&lt;/property&gt;</span>
        <span style="color:#f92672">&lt;property</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;suffix&#34;</span> <span style="color:#a6e22e">value=</span><span style="color:#e6db74">&#34;.jsp&#34;</span><span style="color:#f92672">&gt;&lt;/property&gt;</span>
    <span style="color:#f92672">&lt;/bean&gt;</span>

<span style="color:#f92672">&lt;/beans&gt;</span>

</code></pre></div><h2 id="注解">注解</h2>
<p>xml 已经定义了 handler(类比action,本质为servlet集合) 的扫描路径</p>
<ul>
<li><code>@Controller</code> 控制器, 作用于class, 用于控制路径跳转,类似于web.xml中声明servlet. 可以使用 <code>@RequestMapping</code> 来声明父路径</li>
<li><code>@RequestMapping</code> 可用于class或method,两者共同组成一个完整的url访问路径</li>
<li><code>@PathVariable</code> 路径变量,用来修饰入参,可以映射一个请求路径变量. 路径中使用{var} 型占位符来声明一个路径变量;入参中使用此注解映射路径变量</li>
<li><code>@RequestParam</code> 请求参数,用来修饰入参,可以映射一个请求参数.是一种获得request的param的基础方式</li>
<li><code>@RequestHeader</code> 将request请求头的属性与形参绑定</li>
<li><code>@CookieValue</code> 将request cookie的属性与形参绑定(cookie其实也是header的一个属性)</li>
<li><code>@SessionAttributes(value={&quot;user&quot;}, types={String.class})</code> 定义session域中的属性名称或类型;value和types不是双重约束的关系,而是method中往ModelMap中的存放数据时(首先肯定会在request域中放一份),属性名和value数组中定义的一样的话就会被同时放到session域中;或者类型和types中有一致的也会被放到session域中</li>
<li><code>@ModelAttribute</code> 可以修饰method或dispatcherMethod的入参(两个method不同). 被@ModelAttribute标记的方法相当于一种拦截器或者说前置方法,会在每个目标方法被执行之前被springMVC先调用一次.</li>
</ul>
<h2 id="rest-风格的请求">Rest 风格的请求</h2>
<p><img src="https://gitee.com/alexzshl/picbed/raw/master/image-20201226103633675.png" alt="image-20201226103633675"></p>
<h2 id="使用-pojo">使用 Pojo</h2>
<p>不需要指定注解, 如果method的形参是一个自定义的Pojo型class, 那么spring会将request params 映射至一个Pojo实例(类似于struts 1 的 actionform ), 另外的,jsp中的form组件的name属性需要和Poji的属性一一对应</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#a6e22e">@RequestMapping</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;/testModelAttribute&#34;</span><span style="color:#f92672">)</span>
<span style="color:#66d9ef">public</span> String <span style="color:#a6e22e">testModelAttribute</span><span style="color:#f92672">(</span><span style="color:#a6e22e">@ModelAttribute</span><span style="color:#f92672">(</span>value <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;sss&#34;</span><span style="color:#f92672">)</span> UserA userA<span style="color:#f92672">,</span> HttpServletRequest request<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
    System<span style="color:#f92672">.</span><span style="color:#a6e22e">out</span><span style="color:#f92672">.</span><span style="color:#a6e22e">println</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;Form after ModelAttribute: &#34;</span><span style="color:#f92672">+</span> userA<span style="color:#f92672">);</span>
    <span style="color:#66d9ef">return</span> SUCCESS<span style="color:#f92672">;</span>
<span style="color:#f92672">}</span>
</code></pre></div><p>spring mvc 确定目标方法pojo入参的过程:</p>
<ol>
<li>确定一个key. . 若入参没有使用@ModelAttribute(value=&ldquo;xxx&rdquo;)来指定,则默认值为POJO类名的首字母小写字符串</li>
<li>在 implicitModel中查找key对应的对象. 若存在,则作为参数传入</li>
<li>若不存在对应的key对应的对象,则检查当前的Handler是否使用了@SessionAttribute注解修饰, 若使用了该注解且这个注解的value数组中包含了同名key,则从HttpSeesion中获取key所对应的value, 若存在则直接传入到目标方法的入参中; 若不存在, 则抛出异常</li>
<li>若 handler没有@SessionAttribute注解,或者value中不包含此key, 则通过反射来创建POJO相应类型的参数,传入为目标方法的参数</li>
<li>springmvc会把key和value保存在implicitModel中,进而保存到request中</li>
</ol>
<p><code>@ModelAttribute()</code> 可以用来修饰一个method, 拦截器会在所有servlet方法执行前调用; 也可以用来修饰一个servlet方法的入参,用来将<code>ModelAttribute</code>显式绑定至入参</p>
<h2 id="使用-servlet-api">使用 servlet api</h2>
<p>如何使用原生的 servlet api, 即我们熟悉的以下servlet形参</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java">HttpServletRequest request<span style="color:#f92672">,</span>
HttpServletResponse response<span style="color:#f92672">,</span>
Writer out<span style="color:#f92672">,</span>
</code></pre></div><p>很简单,只需要在method中同样这样声明形参即可, spring会自动根据形参类型来传值(约定方式), 一般情况下返回值应该为void, 由response的writer来输出内容</p>
<h2 id="model-view">Model View</h2>
<p>要解决的是如何处理返回的view(例如jsp)和携带的数据(model), 类似于使用原生servlet时dispather一个jsp路径并且同时向request等域对象中储存数据供jsp使用</p>
<h3 id="返回值类型-modelandview-打包model和view">返回值类型 ModelAndView 打包model和view</h3>
<p>返回值可以指定为 <code>ModelAndView</code> 类型, view即返回/转发的视图(例如jsp), 而model是一个map用来储存attributes, spring后续会将 model 中的数据逐一存入 request 域</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json">    <span style="color:#960050;background-color:#1e0010">@RequestMapping(</span><span style="color:#e6db74">&#34;/testModelAndView&#34;</span><span style="color:#960050;background-color:#1e0010">)</span>
    <span style="color:#960050;background-color:#1e0010">public</span> <span style="color:#960050;background-color:#1e0010">ModelAndView</span> <span style="color:#960050;background-color:#1e0010">testModelAndView()</span> {
        <span style="color:#960050;background-color:#1e0010">String</span> <span style="color:#960050;background-color:#1e0010">viewName</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">SUCCESS;</span>
        <span style="color:#960050;background-color:#1e0010">ModelAndView</span> <span style="color:#960050;background-color:#1e0010">modelAndView</span> <span style="color:#960050;background-color:#1e0010">=</span> <span style="color:#960050;background-color:#1e0010">new</span> <span style="color:#960050;background-color:#1e0010">ModelAndView(viewName);</span>
        <span style="color:#960050;background-color:#1e0010">modelAndView.addObject(</span><span style="color:#f92672">&#34;time&#34;</span>, <span style="color:#960050;background-color:#1e0010">new</span> <span style="color:#960050;background-color:#1e0010">Date());</span>
        <span style="color:#960050;background-color:#1e0010">return</span> <span style="color:#960050;background-color:#1e0010">modelAndView;</span>
    }
</code></pre></div><h3 id="通过形参-map-类型来处理model">通过形参 Map 类型来处理model</h3>
<p>spring 内部会为每个方法新建一个map类型的实例,用于传递model数据. 一旦检测到形参中有map类型的参数,spring 会将引用直接赋给该形参, 对map进行操作其实就是直接操作model. 上面的modelandview其实是一种间接的方式,最终spring都会将数据model储存至map并随着view一起发送给后续处理过程</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json">    <span style="color:#960050;background-color:#1e0010">@RequestMapping(</span><span style="color:#e6db74">&#34;/testMap&#34;</span><span style="color:#960050;background-color:#1e0010">)</span>
    <span style="color:#960050;background-color:#1e0010">public</span> <span style="color:#960050;background-color:#1e0010">String</span> <span style="color:#960050;background-color:#1e0010">testMap(Map&lt;String,</span> <span style="color:#960050;background-color:#1e0010">Object&gt;</span> <span style="color:#960050;background-color:#1e0010">map)</span> {
        <span style="color:#960050;background-color:#1e0010">map.put(</span><span style="color:#f92672">&#34;name&#34;</span>, <span style="color:#f92672">&#34;alex&#34;</span><span style="color:#960050;background-color:#1e0010">);</span>
        <span style="color:#960050;background-color:#1e0010">return</span> <span style="color:#960050;background-color:#1e0010">SUCCESS;</span>
    }
</code></pre></div><h2 id="结果跳转方式">结果跳转方式</h2>
<p>首先说一下用户的请求有两种,一种是需要经过handler的,也就是不以.jsp结尾的路径,这种路径经过sprring mvc处理后交由handler进行处理; 另一种是以.jsp结尾的路径即直接访问资源文件. 为了同时支持这两种访问,一般需要同时具有以下两条配置</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml">    <span style="color:#f92672">&lt;mvc:annotation-driven/&gt;</span>
    <span style="color:#f92672">&lt;mvc:default-servlet-handler/&gt;</span>
</code></pre></div><p>接下来看handler的结果跳转方式,也就是最终的modelandview的view是如何确定的:</p>
<ul>
<li>handler返回一个字符串: 预计请求一个jsp资源文件,需要经过视图解析器补全路径,最后是一个jsp文件路径, 最终以forward形式转发jsp内容</li>
<li>forward:xxx 不经过视图解析器,预计为一个资源路径,一般是用来转发到其他handler. 如果要转发到一个jsp文件,则xxx应该是一个有效的资源路径,类似于使用servlet dispathcer的forward. forward是服务器的操作,forward之后的最终页面发给了客户端</li>
<li>redirect:xxx 不经过视图解析器. 类似于forward,但是获得最终的view之后,服务器不会将view直接返回给客户端,而是发出一个303状态附带上路径,由客户端再次请求新的路径,因此客户端表现为两次请求,浏览器的路径会变化. 一般用于指引用户跳转至其他页面例如首页/登录页等</li>
</ul>
<h2 id="视图和视图解析器">视图和视图解析器</h2>
<p><img src="https://gitee.com/alexzshl/picbed/raw/master/image-20210112193153993.png" alt="image-20201222133728134"></p>
<p>如果项目中使用了jstl, 则SpringMVC会自动把InternalResourceView转为 JstlView</p>
<p>若使用了jstl的fmt标签,则需要在SpringMVC的配置文件中 配置国际化资源文件</p>
<h2 id="json">JSON</h2>
<p>前后端分离</p>
<p>前端独立部署(layui),后端返回json数据后前端自己渲染</p>
<p>JSON 或者 说 JSON 对象其实是一种特定格式的字符串,任何语言的后端只需要将自己语言的对象转换(使用自己语言提供的的json处理库)为JSON格式的字符串发送给前端,前端就可以还原为js对象从而用于渲染页面</p>
<p>JAVA 推荐使用的 JSON 工具: Jackson, fastjson</p>
<p>对于spring而言,只需要在返回类型为对象的方法上加上@ResponseBody注解,那么最终返回的ModelAndView就是一个单纯的JSON格式的字符串</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml"><span style="color:#f92672">&lt;dependency&gt;</span>
  <span style="color:#f92672">&lt;groupId&gt;</span>com.fasterxml.jackson.core<span style="color:#f92672">&lt;/groupId&gt;</span>
  <span style="color:#f92672">&lt;artifactId&gt;</span>jackson-databind<span style="color:#f92672">&lt;/artifactId&gt;</span>
  <span style="color:#f92672">&lt;version&gt;</span>2.12.0<span style="color:#f92672">&lt;/version&gt;</span>
<span style="color:#f92672">&lt;/dependency&gt;</span>

<span style="color:#f92672">&lt;dependency&gt;</span>
  <span style="color:#f92672">&lt;groupId&gt;</span>com.alibaba<span style="color:#f92672">&lt;/groupId&gt;</span>
  <span style="color:#f92672">&lt;artifactId&gt;</span>fastjson<span style="color:#f92672">&lt;/artifactId&gt;</span>
  <span style="color:#f92672">&lt;version&gt;</span>1.2.75<span style="color:#f92672">&lt;/version&gt;</span>
<span style="color:#f92672">&lt;/dependency&gt;</span>
</code></pre></div><h3 id="restcontroller">RestController</h3>
<p>表示这个类是一个controller,并且所有的方法都是隐含的responsebody注解. 对于基本数据类型/包装类和string类型,spring返回的就是tostring,但是返回的编码是iso8xxx,中文会乱码,需要在requestmapping加上produced参数; 除此之外,返回一个pojo对象时,spring会尝试返回json字符串,而且编码已经处理好为utf-8</p>
<h2 id="拦截器">拦截器</h2>
<p>例如: 进行用户权限校验,如果用户不存在或者权限不足,重定向页面</p>
<ul>
<li>拦截器是springmvc自带的,只有使用了mvc框架才能用</li>
<li>拦截器只会拦截访问的控制器方法,对于访问静态资源是不会拦截的</li>
</ul>
<h3 id="modelattribute">@ModelAttribute</h3>
<p>用于修饰 controller 类中的某个方法,是一种内置的拦截器. controller 中所有的mappings方法在运行前都先执行此方法,以便做一些预处理工作, 例如向model中添加数据. mappings方法的形参在传参时,会优先去此model中查找数据,然后用request参数来替换已接收字段</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#a6e22e">@RequestMapping</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;/book/doUpdate&#34;</span><span style="color:#f92672">)</span>
    <span style="color:#66d9ef">public</span> String <span style="color:#a6e22e">doUpdate</span><span style="color:#f92672">(</span>Book book<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
        System<span style="color:#f92672">.</span><span style="color:#a6e22e">out</span><span style="color:#f92672">.</span><span style="color:#a6e22e">println</span><span style="color:#f92672">(</span>book<span style="color:#f92672">);</span>
        bookService<span style="color:#f92672">.</span><span style="color:#a6e22e">update</span><span style="color:#f92672">(</span>book<span style="color:#f92672">);</span>
        <span style="color:#66d9ef">return</span> REDIRECTBOOKS<span style="color:#f92672">;</span>
    <span style="color:#f92672">}</span>
    <span style="color:#a6e22e">@ModelAttribute</span> <span style="color:#75715e">// @ModelAttribute 修饰的方法其实是一个拦截器,该类下其他方法执行前都会调用此方法
</span><span style="color:#75715e"></span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">getBook</span><span style="color:#f92672">(</span><span style="color:#a6e22e">@RequestParam</span><span style="color:#f92672">(</span>value <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;id&#34;</span><span style="color:#f92672">,</span> required <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span><span style="color:#f92672">)</span> String isbn<span style="color:#f92672">,</span> Model model<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
        System<span style="color:#f92672">.</span><span style="color:#a6e22e">out</span><span style="color:#f92672">.</span><span style="color:#a6e22e">println</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;@ModelAttribute -&gt; about book: &#34;</span> <span style="color:#f92672">+</span> isbn <span style="color:#f92672">);</span>
        <span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>isbn <span style="color:#f92672">!=</span> <span style="color:#66d9ef">null</span><span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
            Book book <span style="color:#f92672">=</span> bookService<span style="color:#f92672">.</span><span style="color:#a6e22e">get</span><span style="color:#f92672">(</span>isbn<span style="color:#f92672">);</span>
            model<span style="color:#f92672">.</span><span style="color:#a6e22e">addAttribute</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;book&#34;</span><span style="color:#f92672">,</span> book<span style="color:#f92672">);</span>
        <span style="color:#f92672">}</span>
    <span style="color:#f92672">}</span>
</code></pre></div><h3 id="自定义拦截器">自定义拦截器</h3>
<p>继承 HandlerInterceptor 接口</p>
<h2 id="文件上传">文件上传</h2>
<p>前端:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-html" data-lang="html">&lt;<span style="color:#f92672">form</span> <span style="color:#a6e22e">action</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span> <span style="color:#a6e22e">enctype</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;multipart/form-data&#34;</span> <span style="color:#a6e22e">method</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post&#34;</span>&gt;
</code></pre></div><p>后端:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml">    <span style="color:#f92672">&lt;dependency&gt;</span>
      <span style="color:#f92672">&lt;groupId&gt;</span>commons-fileupload<span style="color:#f92672">&lt;/groupId&gt;</span>
      <span style="color:#f92672">&lt;artifactId&gt;</span>commons-fileupload<span style="color:#f92672">&lt;/artifactId&gt;</span>
      <span style="color:#f92672">&lt;version&gt;</span>1.4<span style="color:#f92672">&lt;/version&gt;</span>
    <span style="color:#f92672">&lt;/dependency&gt;</span>
</code></pre></div><div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml">    <span style="color:#f92672">&lt;bean</span> <span style="color:#a6e22e">class=</span><span style="color:#e6db74">&#34;org.springframework.web.multipart.commons.CommonsMultipartResolver&#34;</span> <span style="color:#a6e22e">id=</span><span style="color:#e6db74">&#34;multipartResolver&#34;</span><span style="color:#f92672">&gt;</span>
        <span style="color:#f92672">&lt;property</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;defaultEncoding&#34;</span> <span style="color:#a6e22e">value=</span><span style="color:#e6db74">&#34;utf-8&#34;</span><span style="color:#f92672">/&gt;</span>
        <span style="color:#f92672">&lt;property</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;maxUploadSize&#34;</span> <span style="color:#a6e22e">value=</span><span style="color:#e6db74">&#34;10485678&#34;</span><span style="color:#f92672">/&gt;</span>
        <span style="color:#f92672">&lt;property</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;maxInMemorySize&#34;</span> <span style="color:#a6e22e">value=</span><span style="color:#e6db74">&#34;40960&#34;</span><span style="color:#f92672">/&gt;</span>
    <span style="color:#f92672">&lt;/bean&gt;</span>
</code></pre></div><p>必须保证: id=&ldquo;multipartResolver&rdquo;, 否则不会生效</p>
<h2 id="国际化-i18n">国际化 i18n</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml">	<span style="color:#f92672">&lt;bean</span> <span style="color:#a6e22e">class=</span><span style="color:#e6db74">&#34;org.springframework.web.servlet.view.InternalResourceViewResolver&#34;</span><span style="color:#f92672">&gt;</span>
        <span style="color:#f92672">&lt;property</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;prefix&#34;</span> <span style="color:#a6e22e">value=</span><span style="color:#e6db74">&#34;/WEB-INF/page/&#34;</span><span style="color:#f92672">&gt;&lt;/property&gt;</span>
        <span style="color:#f92672">&lt;property</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;suffix&#34;</span> <span style="color:#a6e22e">value=</span><span style="color:#e6db74">&#34;.jsp&#34;</span><span style="color:#f92672">&gt;&lt;/property&gt;</span>
    <span style="color:#f92672">&lt;/bean&gt;</span>

    <span style="color:#f92672">&lt;bean</span> <span style="color:#a6e22e">id=</span><span style="color:#e6db74">&#34;messageSource&#34;</span> <span style="color:#a6e22e">class=</span><span style="color:#e6db74">&#34;org.springframework.context.support.ResourceBundleMessageSource&#34;</span><span style="color:#f92672">&gt;</span>
        <span style="color:#f92672">&lt;property</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;basename&#34;</span> <span style="color:#a6e22e">value=</span><span style="color:#e6db74">&#34;i18n&#34;</span><span style="color:#f92672">&gt;&lt;/property&gt;</span>
    <span style="color:#f92672">&lt;/bean&gt;</span>

    <span style="color:#f92672">&lt;mvc:annotation-driven/&gt;</span>

    <span style="color:#f92672">&lt;mvc:view-controller</span> <span style="color:#a6e22e">path=</span><span style="color:#e6db74">&#34;/i18n&#34;</span> <span style="color:#a6e22e">view-name=</span><span style="color:#e6db74">&#34;i18n&#34;</span><span style="color:#f92672">&gt;&lt;/mvc:view-controller&gt;</span>
    <span style="color:#f92672">&lt;mvc:view-controller</span> <span style="color:#a6e22e">path=</span><span style="color:#e6db74">&#34;/aaa&#34;</span> <span style="color:#a6e22e">view-name=</span><span style="color:#e6db74">&#34;aaa&#34;</span><span style="color:#f92672">&gt;&lt;/mvc:view-controller&gt;</span>
    <span style="color:#f92672">&lt;mvc:view-controller</span> <span style="color:#a6e22e">path=</span><span style="color:#e6db74">&#34;/bbb&#34;</span> <span style="color:#a6e22e">view-name=</span><span style="color:#e6db74">&#34;bbb&#34;</span><span style="color:#f92672">&gt;&lt;/mvc:view-controller&gt;</span>
</code></pre></div><p>注意: <code>id=&quot;messageSource&quot;</code> 必须有这个,而且不能起别的名字.具体原因未知,如果不这样定义 jstl-fmt 会找不到资源信息(表现为页面中fmt标签处出现类似???的字符). 另外一点就是检查idea中对properties的编码配置. 另外一点是首页不经过springmvc,因此无法使用国际化资源,需要额外的处理(例如将首页交由springmvc处理)(原因是在web.xml中配置的DispatcherServlet的url-pattern为“/”，不会匹配访问.jsp的url，所以直接访问首页并不会经过DispatcherServlet，导致无法读取到资源文件)</p>
<p>另外一个奇怪的现象是:一切都设置好了但是页面依然乱码,properties中文突然加入一段unicode字符串之后就全好了</p>
<p>idea在打开properties文件时,对于中文也是显示的中文,但是这是一个假象,idea已经对显示做了一层转换,如果用记事本打开看,properties文件中的中文其实都是unicode字符串(如果idea中勾选了properties文件的asc转换).所以如果页面乱码,一定要用记事本打开资源文件看看是否是unicode</p>
<p><img src="https://gitee.com/alexzshl/picbed/raw/master/image-20201222133728134.png" alt="image-20210112193153993"></p>
<pre><code class="language-jsp" data-lang="jsp">&lt;%@ taglib prefix=&quot;fmt&quot; uri=&quot;http://java.sun.com/jsp/jstl/fmt&quot; %&gt;
&lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&gt;

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;zh-CN&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;title&gt;Title&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;fmt:message key=&quot;i18n.username&quot;&gt;&lt;/fmt:message&gt;
&lt;fmt:message key=&quot;i18n.password&quot;&gt;&lt;/fmt:message&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>另外需要注意的是index.jsp的问题,多数人可能在测试的时候,index.jsp直接放在web根目录下,其实此时的index.jsp并没有经过spring的转发(spring中配置了bundle信息,即basename,这样在jsp中可以省略掉bundle标签),页面中是无法获取上面的fmt信息的,而经过spring直接转发的jsp页面则显示正常. 当然,如果使用完全的fmt标签则在index.jsp中也可以正常显示,如下所示:</p>
<pre><code class="language-jsp" data-lang="jsp">&lt;fmt:bundle basename=&quot;i18n&quot;&gt;
    &lt;fmt:message key=&quot;i18n.username&quot;&gt;&lt;/fmt:message&gt; &lt;br&gt;
&lt;/fmt:bundle&gt;
</code></pre><p>虽然两者都可以正常显示,但是经由spring配置后,在IDEA中写jsp时可以获得更好的代码提示,而直接使用<code>fmt:bundle</code>是没有代码提示的,需要自己保证资源文件名的正确性</p>
<h3 id="通过请求参数来切换local">通过请求参数来切换local</h3>
<p>首先配置locale拦截器和解释器: 注意 id 是默认值,不能自定义(个人还没接触到更细粒度的配置,也许可以自定义id, 但是需要更基础的配置来绑定resolver).</p>
<p>关于很多内置bean的id必须定义而且为固定值的个人理解: IOC 作为一个 bean 容器,不仅仅只有用户定义的bean, 特别是使用SpringMVC的时候,框架本身会提供大量的内置bean运行在IOC底层,而很多时候用户的配置其实就是一个覆盖系统内置bean的过程. bean如果要覆盖,靠的就是id,相当于往map中put一个key相同的对象,就完成了覆盖. 没有用户的配置mvc也能工作,用户的配置主要就是覆盖mvc的默认配置或者扩展/开启mvc的其他功能</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml"><span style="color:#75715e">&lt;!--    配置 SessionLocalResolver--&gt;</span>
    <span style="color:#f92672">&lt;bean</span> <span style="color:#a6e22e">class=</span><span style="color:#e6db74">&#34;org.springframework.web.servlet.i18n.SessionLocaleResolver&#34;</span> <span style="color:#a6e22e">id=</span><span style="color:#e6db74">&#34;localeResolver&#34;</span><span style="color:#f92672">&gt;&lt;/bean&gt;</span>
<span style="color:#75715e">&lt;!--    配置 local 拦截器--&gt;</span>
    <span style="color:#f92672">&lt;mvc:interceptors&gt;</span>
        <span style="color:#f92672">&lt;bean</span> <span style="color:#a6e22e">class=</span><span style="color:#e6db74">&#34;org.springframework.web.servlet.i18n.LocaleChangeInterceptor&#34;</span><span style="color:#f92672">&gt;&lt;/bean&gt;</span>
    <span style="color:#f92672">&lt;/mvc:interceptors&gt;</span>
</code></pre></div><p>然后页面中提供包含locale信息的超链接(指向当前页面+locale请求参数), 其他地方不需要改变, 即便是直接转发的jsp路径,也可以实现点击超链接切换本地化信息</p>
<pre><code class="language-jsp" data-lang="jsp">&lt;a href=&quot;${pageContext.request.contextPath}/i18n?locale=zh_CN&quot;&gt;中文&lt;/a&gt;
&lt;a href=&quot;${pageContext.request.contextPath}/i18n?locale=en_US&quot;&gt;English&lt;/a&gt; &lt;br&gt;&lt;br&gt;

&lt;fmt:message key=&quot;i18n.username&quot;&gt;&lt;/fmt:message&gt;
&lt;fmt:message key=&quot;i18n.password&quot;&gt;&lt;/fmt:message&gt;
</code></pre><h2 id="数据校验">数据校验</h2>
<h3 id="jsr303-规范">JSR303 规范</h3>
<p>定义了一组校验规范,相当于定义了一个接口</p>
<p>在bean属性上标注类似于 @NotNull @Max 等标准的注解指定校验规则,并通过标准的验证接口对bean进行验证</p>
<ul>
<li>@Null 必须为null</li>
<li>@NotNull 必须为非null</li>
<li>@AssertTrue 必须为true</li>
<li>@AssertFalse 必须为false</li>
<li>@Min(value) 必须是一个数字而且大于等于value</li>
<li>@Max(value) 必须是一个数字而且小于等于value</li>
<li>@DecimalMin(value)</li>
<li>@DecimalMax(value)</li>
<li>@Size(max, min) 大小必须在指定范围内</li>
<li>@Digits(integer, fraction) 必须是一个数字,大小在可接受范围内</li>
<li>@Past 过去的时间</li>
<li>@Future 未来的时间</li>
<li>@Pattern(value) 自定义正则校验,必须符合正则表达式</li>
</ul>
<h3 id="hibernate-validator">Hibernate Validator</h3>
<p>是jsr303的一个实现,除了支持所有标准的校验注解外,还支持以下扩展注解:</p>
<ul>
<li>@Email 必须是一个电子邮箱地址(内置正则校验)</li>
<li>@Length 被注释的字符串大小必须在指定的范围内</li>
<li>@NotEmpty 字符串必须非空</li>
<li>@Range 被注释的元素必须在合适的范围内</li>
</ul>
<h3 id="spring-mvc-数据校验">Spring MVC 数据校验</h3>
<p>Spring 拥有自己独立的数据校验框架, 同时支持JSR303标准的数据校验框架</p>
<p>Spring在进行数据绑定时,可同时调用校验框架完成 校验工作. 在SpringMVC中可以直接通过注解驱动的方式进行数据校验</p>
<p>LocalValidationFactoryBean 既实现了Spring的validator接口,也实现了jsr303的validator接口.只需要在容器中定义此bean,即可将其注入到需要数据校验的bean中(mvc:annotation-driven 会默认装配好一个)</p>
<p>在目标方法bean类型的前面添加 @Valid 注解</p>
<p>Spring本身并没有JSR303的实现,所以需要将JSR303的实现加入类路径下,例如 Hibernate Validator</p>
<h2 id="json-and-ajax">JSON and AJAX</h2>
<p>需要:</p>
<ul>
<li>引入依赖 <code>jackson-databind</code>. Spring默认使用jackcon来处理json,一旦检测到jackson依赖,则spring会装载bean: MappingJackson2HttpMessageConverter</li>
<li>mapping上添加注解 @ResponseBody, 返回值为对象或者直接用 Object</li>
</ul>
<p>原理: HttpMessageConverter</p>
<p>服务器除了可以返回json数据,还可以处理请求参数为json类型,入参上使用 @RequestBody,即可将传入的json参数转换为java对象</p>
<h2 id="拦截器-1">拦截器</h2>
<p>在请求进入tomcat之后,handler处理请求之前调用拦截器</p>
<p>过滤器的位置更加靠外面,过滤器之后才是拦截器</p>
<h3 id="自定义拦截器-1">自定义拦截器</h3>
<p>步骤:</p>
<ol>
<li>编写自定义类实现接口<code>org.springframework.web.servlet.HandlerInterceptor</code></li>
<li>springmvc中配置拦截器</li>
</ol>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml">    <span style="color:#f92672">&lt;mvc:interceptors&gt;</span>
        <span style="color:#f92672">&lt;bean</span> <span style="color:#a6e22e">class=</span><span style="color:#e6db74">&#34;com.alex.interceptor.TestInterceptor&#34;</span><span style="color:#f92672">&gt;&lt;/bean&gt;</span>
        <span style="color:#f92672">&lt;mvc:interceptor&gt;</span>
            <span style="color:#f92672">&lt;mvc:mapping</span> <span style="color:#a6e22e">path=</span><span style="color:#e6db74">&#34;/admin/**&#34;</span><span style="color:#f92672">/&gt;</span>
            <span style="color:#f92672">&lt;mvc:exclude-mapping</span> <span style="color:#a6e22e">path=</span><span style="color:#e6db74">&#34;/admin/login/**&#34;</span><span style="color:#f92672">/&gt;</span>
            <span style="color:#f92672">&lt;mvc:exclude-mapping</span> <span style="color:#a6e22e">path=</span><span style="color:#e6db74">&#34;/admin/doLogin/**&#34;</span><span style="color:#f92672">/&gt;</span>
            <span style="color:#f92672">&lt;bean</span> <span style="color:#a6e22e">class=</span><span style="color:#e6db74">&#34;com.alex.interceptor.LoginInterceptor&#34;</span><span style="color:#f92672">&gt;&lt;/bean&gt;</span>
        <span style="color:#f92672">&lt;/mvc:interceptor&gt;</span>
    <span style="color:#f92672">&lt;/mvc:interceptors&gt;</span>
</code></pre></div><h3 id="生命周期">生命周期</h3>
<p>拦截器接口有三个方法:</p>
<ul>
<li>preHandle: 在目标方法之前被调用;若返回值为true,则继续调用后续拦截器;若返回值为false,则不再调用后续拦截器,此时一般选择重定向到其他页面. 可以考虑做权限,日志,事务等</li>
<li>postHandle: 在调用目标方法之后,渲染视图之前. 可以对请求域中的属性或视图做修改</li>
<li>afterHandle: 渲染视图之后. 释放资源</li>
</ul>
<h3 id="拦截器顺序">拦截器顺序</h3>
<p>prehandle 按配置的正序执行</p>
<p>posthandle和afterhandle 按配置的反序执行</p>
<p><img src="https://gitee.com/alexzshl/picbed/raw/master/image-20210113144610855.png" alt="image-20210113144610855"></p>
<h2 id="异常处理">异常处理</h2>
<p>SringMVC 通过 HandlerExceptionResolver 处理程序的异常, 包括 Handler 映射,数据绑定,以及目标方法执行时发生的异常</p>
<p>handler中可以定义异常处理函数,作用于当前handler</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#a6e22e">@ExceptionHandler</span><span style="color:#f92672">({</span>ArithmeticException<span style="color:#f92672">.</span><span style="color:#a6e22e">class</span><span style="color:#f92672">})</span>
<span style="color:#66d9ef">private</span> String <span style="color:#a6e22e">handleArithmeticException</span><span style="color:#f92672">(</span>Exception e<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
    System<span style="color:#f92672">.</span><span style="color:#a6e22e">out</span><span style="color:#f92672">.</span><span style="color:#a6e22e">println</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;异常: &#34;</span> <span style="color:#f92672">+</span> e<span style="color:#f92672">);</span>
    <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;error&#34;</span><span style="color:#f92672">;</span>
<span style="color:#f92672">}</span>
</code></pre></div><p>入参中不能传入map,否则此方法会失效</p>
<p>可以通过返回 MV 来传递异常信息给页面</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#a6e22e">@ExceptionHandler</span><span style="color:#f92672">({</span>ArithmeticException<span style="color:#f92672">.</span><span style="color:#a6e22e">class</span><span style="color:#f92672">})</span>
<span style="color:#66d9ef">private</span> ModelAndView <span style="color:#a6e22e">handleArithmeticException</span><span style="color:#f92672">(</span>Exception e<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
    System<span style="color:#f92672">.</span><span style="color:#a6e22e">out</span><span style="color:#f92672">.</span><span style="color:#a6e22e">println</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;异常: &#34;</span> <span style="color:#f92672">+</span> e<span style="color:#f92672">);</span>
    ModelAndView mv <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> ModelAndView<span style="color:#f92672">(</span><span style="color:#e6db74">&#34;error&#34;</span><span style="color:#f92672">);</span>
    mv<span style="color:#f92672">.</span><span style="color:#a6e22e">addObject</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;error&#34;</span><span style="color:#f92672">,</span> e<span style="color:#f92672">);</span>
    <span style="color:#66d9ef">return</span> mv<span style="color:#f92672">;</span>
<span style="color:#f92672">}</span>
</code></pre></div><p>定义多个异常处理方法时,异常处理有优先级的问题: 优先匹配更具体更精确的异常类型(最小子类)</p>
<p>也可以定义一个全局的异常处理类,作用于所有handler</p>
<p>如果在当前handler中找不到 <code>@ExceptionHandler</code> 标记的异常,那就去<code>@ControllerAdvice</code>标记的类中查找异常处理方法</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#a6e22e">@ControllerAdvice</span>
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MyExceptionHandler</span> <span style="color:#f92672">{</span>

    <span style="color:#a6e22e">@ExceptionHandler</span><span style="color:#f92672">({</span>ArithmeticException<span style="color:#f92672">.</span><span style="color:#a6e22e">class</span><span style="color:#f92672">})</span>
    <span style="color:#66d9ef">private</span> ModelAndView <span style="color:#a6e22e">handleArithmeticException</span><span style="color:#f92672">(</span>Exception e<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
        System<span style="color:#f92672">.</span><span style="color:#a6e22e">out</span><span style="color:#f92672">.</span><span style="color:#a6e22e">println</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;--&gt;异常: &#34;</span> <span style="color:#f92672">+</span> e<span style="color:#f92672">);</span>
        ModelAndView mv <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> ModelAndView<span style="color:#f92672">(</span><span style="color:#e6db74">&#34;error&#34;</span><span style="color:#f92672">);</span>
        mv<span style="color:#f92672">.</span><span style="color:#a6e22e">addObject</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;error&#34;</span><span style="color:#f92672">,</span> e<span style="color:#f92672">);</span>
        <span style="color:#66d9ef">return</span> mv<span style="color:#f92672">;</span>
    <span style="color:#f92672">}</span>
<span style="color:#f92672">}</span>
</code></pre></div><p><code>@ControllerAdvice</code> 的理解: 这里用到的是aop概念.这个注解的名字定义的很直观.我们知道可以在每个handler中定义@ExceptionHandler, 而 <code>@ControllerAdvice</code> 这个注解顾名思义就是定义了一个 controller 切面,意思就是该类下的所有方法会插入所有的controller,这就是全局的意思.所以不难想象,这个注解并不是仅仅用于异常处理</p>
<h3 id="responsestatusexceptionresolver">ResponseStatusExceptionResolver</h3>
<p>下面的 Resolver 都是 HandlerExceptionResolver 的一些实现类</p>
<p>HTTP 异常解析器</p>
<h4 id="核心注解-responsestatus">核心注解: @ResponseStatus</h4>
<p>可用于修饰一个自定义异常类: 如果handler中抛出了此异常,则页面最终会显示此定制的异常信息. 类似于 HTTP-500,HTTP-404 那样的HTTP异常页面</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#a6e22e">@ResponseStatus</span><span style="color:#f92672">(</span>value <span style="color:#f92672">=</span> HttpStatus<span style="color:#f92672">.</span><span style="color:#a6e22e">BAD_REQUEST</span><span style="color:#f92672">,</span> reason <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;ALEX&#34;</span><span style="color:#f92672">)</span>
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">AlexException</span> <span style="color:#66d9ef">extends</span> RuntimeException<span style="color:#f92672">{</span>

    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> <span style="color:#66d9ef">long</span> serialVersionUID <span style="color:#f92672">=</span> 1L<span style="color:#f92672">;</span>

<span style="color:#f92672">}</span>
</code></pre></div><p>可用于修饰一个handler方法: 如果handler没有抛出异常,正常执行,则页面最终会显示此定制的页面,虽然看上去像是产生了异常,但实际上可能方法并没有抛出任何异常,而且执行是成功的. 可以用于定义一些路径,这些路径就是用来返回此异常信息的,而不处理实际业务,这样在其他handler中可以直接跳转到此路径以显示信息而不是手动抛出异常</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java">    <span style="color:#a6e22e">@ResponseStatus</span><span style="color:#f92672">(</span>value <span style="color:#f92672">=</span> HttpStatus<span style="color:#f92672">.</span><span style="color:#a6e22e">NOT_FOUND</span><span style="color:#f92672">,</span> reason <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;测试-MAPPING: 这个请求路径被设计为正常情况下(方法体内不产生异常时)返回一个HTTP异常&#34;</span><span style="color:#f92672">)</span>
    <span style="color:#a6e22e">@RequestMapping</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;/test/statusCode/01&#34;</span><span style="color:#f92672">)</span>
    <span style="color:#66d9ef">public</span> String <span style="color:#a6e22e">test02</span><span style="color:#f92672">(</span><span style="color:#a6e22e">@RequestParam</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;i&#34;</span><span style="color:#f92672">)</span> <span style="color:#66d9ef">int</span> i<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
        <span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>i <span style="color:#f92672">==</span> 13<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
            <span style="color:#66d9ef">throw</span>  <span style="color:#66d9ef">new</span> UserNameNotMatchException<span style="color:#f92672">();</span>
        <span style="color:#f92672">}</span>
        <span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>i <span style="color:#f92672">==</span> 14<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
            <span style="color:#66d9ef">throw</span>  <span style="color:#66d9ef">new</span> AlexException<span style="color:#f92672">();</span>
        <span style="color:#f92672">}</span>
        System<span style="color:#f92672">.</span><span style="color:#a6e22e">out</span><span style="color:#f92672">.</span><span style="color:#a6e22e">println</span><span style="color:#f92672">();</span>
        <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;test/success&#34;</span><span style="color:#f92672">;</span>
    <span style="color:#f92672">}</span>
</code></pre></div><h3 id="defaulthandlerexceptionresolver">DefaultHandlerExceptionResolver</h3>
<p>spring mvc 内置的http特定异常处理器, 用于处理一些Spring自己定义的HTTP异常,例如找不到handler时抛出的异常; 又比如经典的异常: 请求方法不允许(GET? / POST?)</p>
<p>该 resolver 不需要人为配置</p>
<h3 id="simplemappingexceptionresolver">SimpleMappingExceptionResolver</h3>
<p>简单映射异常处理器,需要显式配置此bean</p>
<p>可以用于简单地定义 异常-&gt;ErrorPage 映射关系</p>
<p>相比于 <code>@ExceptionHandler</code> 方式,因为是编写java方法,因此可以进行任何想要的处理方式. 而 SimpleMappingExceptionResolver 则简单地将异常映射到页面,一旦出现了相应的异常,直接转发到相应页面进行显示,而且默认会在 RequestScope 中写入 exception 对象(key=&ldquo;exception&rdquo;), errorpage可以获取到excetion对象.</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml">    <span style="color:#f92672">&lt;bean</span> <span style="color:#a6e22e">class=</span><span style="color:#e6db74">&#34;org.springframework.web.servlet.handler.SimpleMappingExceptionResolver&#34;</span><span style="color:#f92672">&gt;</span>
        <span style="color:#f92672">&lt;property</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;exceptionMappings&#34;</span><span style="color:#f92672">&gt;</span>
            <span style="color:#f92672">&lt;props&gt;</span>
                <span style="color:#f92672">&lt;prop</span> <span style="color:#a6e22e">key=</span><span style="color:#e6db74">&#34;java.lang.ArrayIndexOutOfBoundsException&#34;</span><span style="color:#f92672">&gt;</span>error<span style="color:#f92672">&lt;/prop&gt;</span>
            <span style="color:#f92672">&lt;/props&gt;</span>
        <span style="color:#f92672">&lt;/property&gt;</span>
    <span style="color:#f92672">&lt;/bean&gt;</span>
</code></pre></div><h2 id="springmvc-运行流程">SpringMVC 运行流程</h2>
<p>用户发出请求</p>
<p>存在对应的映射?: 如果存在,下一步; 如果不存在, 看是否配置了 <code>&lt;mvc:default-servlet-handler&gt;</code>,如果配置了则试图直接返回目标资源,否则返回404</p>
<p>存在对应映射</p>
<p>由 HandlerMapping 获取 HandlerExcutionChain 对象: HandlerExcutionChain 包含了 拦截器/目标处理器/目标方法. HandlerMapping 定义了请求到处理器之间的映射</p>
<p>获取 HandlerAdapter 对象: 适配器. 定义了数据绑定/表单验证等处理过程</p>
<p>调用拦截器的 PreHandle 方法</p>
<p>调用目标 Handler 方法得到 ModelandView 对象</p>
<p>调用拦截器的 PostHandle 方法</p>
<p>是否存在异常: 如果有异常, 下一步HandleExceptionResolver 组件处理异常,得到新的 ModelAndView 对象; 如果没有异常, 下一步</p>
<p>由 VIewResover 视图解析器 组件根据 ModelAndView 对象得到实际的View</p>
<p>渲染视图</p>
<p>调用拦截器的 afterHandle 方法,释放资源</p>
<p><img src="https://gitee.com/alexzshl/picbed/raw/master/image-20210113181759314.png" alt="image-20210113165126584"></p>
<h2 id="spring-整合-springmvc">Spring 整合 SpringMVC</h2>
<p>在 Spring MVC 的配置文件中引用业务层的 Bean:</p>
<p>多个 Spring IOC 容器之间可以设置为父子关系,以实现良好的解耦</p>
<p>Spring MVC WEB 层容器可以作为 &ldquo;业务层&rdquo; Spring 容器的子容器: 即 web 层容器可以引用业务层容器的bean, 而业务层容器却访问不到web层容器的 bean</p>
<p>总结: springmvc的配置文件仅仅处理handler(controller)的配置,其他的如数据源/dao/service等则由传统的spring配置文件自己管理. mvc的配置文件作为spring配置文件的子ico容器存在</p>
<p><img src="https://gitee.com/alexzshl/picbed/raw/master/image-20210113165126584.png" alt="image-20210113181759314"></p>
<h3 id="整合ssm">整合SSM</h3>
<h4 id="环境要求">环境要求</h4>
<p>环境:</p>
<ul>
<li>IDEA</li>
<li>MySQL</li>
<li>Tomcat</li>
<li>Maven 3.6</li>
</ul>
<p><strong>Spring框架Web页面乱码问题</strong></p>
<p>在做java Web 项目时，乱码问题时常都会出现，解决方法也不尽相同，有简单也有复杂的；如果加入了Spring框架之后就不一样了，可以采用Spring框架自带的过滤器CharacterEncodingFilter，这样可以大大减轻了我们的工作量，即简单方便又容易理解，配置方式如下：在web.xml文件中filter的位置(最好放在第一位,放后面可能无效果)加上如下内：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml"><span style="color:#f92672">&lt;filter&gt;</span>
    <span style="color:#f92672">&lt;filter-name&gt;</span>encodingFilter<span style="color:#f92672">&lt;/filter-name &gt;</span>
    <span style="color:#f92672">&lt;filter-class&gt;</span>org.springframework.web.filter.CharacterEncodingFilter<span style="color:#f92672">&lt;/filter-class&gt;</span>
    <span style="color:#f92672">&lt;init-param&gt;</span>
        <span style="color:#f92672">&lt;param-name&gt;</span>encoding<span style="color:#f92672">&lt;/param-name&gt;</span>
        <span style="color:#f92672">&lt;param-value&gt;</span>UTF-8<span style="color:#f92672">&lt;/param-value&gt;</span>
    <span style="color:#f92672">&lt;/init-param&gt;</span>
    <span style="color:#f92672">&lt;init-param&gt;</span>
        <span style="color:#f92672">&lt;param-name&gt;</span>forceEncoding<span style="color:#f92672">&lt;/param-name&gt;</span>
        <span style="color:#f92672">&lt;param-value&gt;</span>true<span style="color:#f92672">&lt;/param-value&gt;</span>
    <span style="color:#f92672">&lt;/init-param&gt;</span>
<span style="color:#f92672">&lt;/filter&gt;</span>
<span style="color:#f92672">&lt;filter-mapping&gt;</span>
    <span style="color:#f92672">&lt;filter-name&gt;</span>encodingFilter<span style="color:#f92672">&lt;/filter-name&gt;</span>
    <span style="color:#f92672">&lt;url-pattern&gt;</span>/*<span style="color:#f92672">&lt;/url-pattern&gt;</span>
<span style="color:#f92672">&lt;/filter-mapping&gt;</span>
</code></pre></div>
    
      
    
  </article>
<aside class="sidebar">
  <section class="sidebar_inner">
    
    <h2 class="mt-4">Featured Posts</h2>
    <ul>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/java%E7%99%BB%E5%BD%95%E6%8A%80%E6%9C%AF%E6%80%BB%E7%BB%93/" class="nav-link">Java登录技术总结</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/java%E5%90%8E%E7%AB%AF%E6%95%B4%E5%90%88%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95%E5%8A%9F%E8%83%BD/" class="nav-link">Java后端整合微信登录功能</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/termux/" class="nav-link">Termux</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/activemq/" class="nav-link">ActiveMQ</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/bitwarden/" class="nav-link">Bitwarden</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/centos7/" class="nav-link">CentOS_7</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/docker/" class="nav-link">Docker</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/idea%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7/" class="nav-link">Idea使用技巧积累</a>
      </li>
    </ul>
    <h2 class="mt-4">Recent Posts</h2>
    <ul class="flex-column">
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/java%E7%99%BB%E5%BD%95%E6%8A%80%E6%9C%AF%E6%80%BB%E7%BB%93/" class="nav-link">Java登录技术总结</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/java%E5%90%8E%E7%AB%AF%E6%95%B4%E5%90%88%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95%E5%8A%9F%E8%83%BD/" class="nav-link">Java后端整合微信登录功能</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/termux/" class="nav-link">Termux</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/activemq/" class="nav-link">ActiveMQ</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/bitwarden/" class="nav-link">Bitwarden</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/centos7/" class="nav-link">CentOS_7</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/docker/" class="nav-link">Docker</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/idea%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7/" class="nav-link">Idea使用技巧积累</a>
      </li>
    </ul>
    <div>
      <h2 class="mt-4 taxonomy" id="categories-section">Categories</h2>
      <nav class="tags_nav">
        <a href='https://alexzshl.gitee.io/blog/categories/java/' class="post_tag button button_translucent">
          JAVA
          <span class="button_tally">12</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/linux/' class="post_tag button button_translucent">
          LINUX
          <span class="button_tally">3</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/spring/' class="post_tag button button_translucent">
          SPRING
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/tool/' class="post_tag button button_translucent">
          TOOL
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/web/' class="post_tag button button_translucent">
          WEB
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/book/' class="post_tag button button_translucent">
          BOOK
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/centos/' class="post_tag button button_translucent">
          CENTOS
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/database/' class="post_tag button button_translucent">
          DATABASE
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/devops/' class="post_tag button button_translucent">
          DEVOPS
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/docker/' class="post_tag button button_translucent">
          DOCKER
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/framework/' class="post_tag button button_translucent">
          FRAMEWORK
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/ide/' class="post_tag button button_translucent">
          IDE
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/idea/' class="post_tag button button_translucent">
          IDEA
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/internet/' class="post_tag button button_translucent">
          INTERNET
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/javascript-framework/' class="post_tag button button_translucent">
          JAVASCRIPT-FRAMEWORK
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/json/' class="post_tag button button_translucent">
          JSON
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/lib/' class="post_tag button button_translucent">
          LIB
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/login/' class="post_tag button button_translucent">
          LOGIN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/maven/' class="post_tag button button_translucent">
          MAVEN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/messaging/' class="post_tag button button_translucent">
          MESSAGING
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/mysql/' class="post_tag button button_translucent">
          MYSQL
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/orm/' class="post_tag button button_translucent">
          ORM
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/security/' class="post_tag button button_translucent">
          SECURITY
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/springboot/' class="post_tag button button_translucent">
          SPRINGBOOT
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/springcloud/' class="post_tag button button_translucent">
          SPRINGCLOUD
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/springdata/' class="post_tag button button_translucent">
          SPRINGDATA
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/springmvc/' class="post_tag button button_translucent">
          SPRINGMVC
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/ssh/' class="post_tag button button_translucent">
          SSH
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/terminal/' class="post_tag button button_translucent">
          TERMINAL
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/web-framework/' class="post_tag button button_translucent">
          WEB-FRAMEWORK
          <span class="button_tally">1</span>
        </a>
        
        
      </nav>
    </div>
    <div>
      <h2 class="mt-4 taxonomy" id="tags-section">Tags</h2>
      <nav class="tags_nav">
        <a href='https://alexzshl.gitee.io/blog/tags/activemq/' class="post_tag button button_translucent">
          ACTIVEMQ
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/docker/' class="post_tag button button_translucent">
          DOCKER
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/elasticsearch/' class="post_tag button button_translucent">
          ELASTICSEARCH
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/git/' class="post_tag button button_translucent">
          GIT
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/login/' class="post_tag button button_translucent">
          LOGIN
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/maven/' class="post_tag button button_translucent">
          MAVEN
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/mysql/' class="post_tag button button_translucent">
          MYSQL
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/redis/' class="post_tag button button_translucent">
          REDIS
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/ssh/' class="post_tag button button_translucent">
          SSH
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/404/' class="post_tag button button_translucent">
          404
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/aka.ms/' class="post_tag button button_translucent">
          AKA.MS
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/authorized_keys/' class="post_tag button button_translucent">
          AUTHORIZED_KEYS
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/bitwarden/' class="post_tag button button_translucent">
          BITWARDEN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/centos/' class="post_tag button button_translucent">
          CENTOS
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/consul/' class="post_tag button button_translucent">
          CONSUL
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/debug/' class="post_tag button button_translucent">
          DEBUG
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/design-pattern/' class="post_tag button button_translucent">
          DESIGN-PATTERN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/docker-compose/' class="post_tag button button_translucent">
          DOCKER-COMPOSE
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/effective-java/' class="post_tag button button_translucent">
          EFFECTIVE-JAVA
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/eureka/' class="post_tag button button_translucent">
          EUREKA
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/feign/' class="post_tag button button_translucent">
          FEIGN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/fish/' class="post_tag button button_translucent">
          FISH
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/gateway/' class="post_tag button button_translucent">
          GATEWAY
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/google/' class="post_tag button button_translucent">
          GOOGLE
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/hibernate/' class="post_tag button button_translucent">
          HIBERNATE
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/hystrix/' class="post_tag button button_translucent">
          HYSTRIX
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/interface-document/' class="post_tag button button_translucent">
          INTERFACE-DOCUMENT
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/jackson/' class="post_tag button button_translucent">
          JACKSON
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/jpa/' class="post_tag button button_translucent">
          JPA
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/json/' class="post_tag button button_translucent">
          JSON
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/jsr-107/' class="post_tag button button_translucent">
          JSR-107
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/keygen/' class="post_tag button button_translucent">
          KEYGEN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/messaging/' class="post_tag button button_translucent">
          MESSAGING
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/microsoft/' class="post_tag button button_translucent">
          MICROSOFT
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/nacos/' class="post_tag button button_translucent">
          NACOS
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/nginx/' class="post_tag button button_translucent">
          NGINX
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/npm/' class="post_tag button button_translucent">
          NPM
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/rsa/' class="post_tag button button_translucent">
          RSA
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/security/' class="post_tag button button_translucent">
          SECURITY
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/shell/' class="post_tag button button_translucent">
          SHELL
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/springcloud-alibaba/' class="post_tag button button_translucent">
          SPRINGCLOUD-ALIBABA
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/springmvc/' class="post_tag button button_translucent">
          SPRINGMVC
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/ssh-add/' class="post_tag button button_translucent">
          SSH-ADD
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/ssh-agent/' class="post_tag button button_translucent">
          SSH-AGENT
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/ssh-keygen/' class="post_tag button button_translucent">
          SSH-KEYGEN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/stackoverflow/' class="post_tag button button_translucent">
          STACKOVERFLOW
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/swagger/' class="post_tag button button_translucent">
          SWAGGER
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/task/' class="post_tag button button_translucent">
          TASK
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/tencent-cloud/' class="post_tag button button_translucent">
          TENCENT-CLOUD
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/termux/' class="post_tag button button_translucent">
          TERMUX
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/vue.js/' class="post_tag button button_translucent">
          VUE.JS
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/vue.js-2/' class="post_tag button button_translucent">
          VUE.JS-2
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/web/' class="post_tag button button_translucent">
          WEB
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/wechat/' class="post_tag button button_translucent">
          WECHAT
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/weixin/' class="post_tag button button_translucent">
          WEIXIN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/yum/' class="post_tag button button_translucent">
          YUM
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/zookeeper/' class="post_tag button button_translucent">
          ZOOKEEPER
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/zsh/' class="post_tag button button_translucent">
          ZSH
          <span class="button_tally">1</span>
        </a>
        
        
      </nav>
    </div>
  </section>
</aside>

</div>
    </main><svg width="0" height="0" class="hidden">
  <symbol viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" id="facebook">
    <path d="M437 0H75C33.648 0 0 33.648 0 75v362c0 41.352 33.648 75 75 75h151V331h-60v-90h60v-61c0-49.629 40.371-90 90-90h91v90h-91v61h91l-15 90h-76v181h121c41.352 0 75-33.648 75-75V75c0-41.352-33.648-75-75-75zm0 0"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18.001 18.001" id="twitter">
    <path d="M15.891 4.013c.808-.496 1.343-1.173 1.605-2.034a8.68 8.68 0 0 1-2.351.861c-.703-.756-1.593-1.14-2.66-1.14-1.043 0-1.924.366-2.643 1.078a3.56 3.56 0 0 0-1.076 2.605c0 .309.039.585.117.819-3.076-.105-5.622-1.381-7.628-3.837-.34.601-.51 1.213-.51 1.846 0 1.301.549 2.332 1.645 3.089-.625-.053-1.176-.211-1.645-.47 0 .929.273 1.705.82 2.388a3.623 3.623 0 0 0 2.115 1.291c-.312.08-.641.118-.979.118-.312 0-.533-.026-.664-.083.23.757.664 1.371 1.291 1.841a3.652 3.652 0 0 0 2.152.743C4.148 14.173 2.625 14.69.902 14.69c-.422 0-.721-.006-.902-.038 1.697 1.102 3.586 1.649 5.676 1.649 2.139 0 4.029-.542 5.674-1.626 1.645-1.078 2.859-2.408 3.639-3.974a10.77 10.77 0 0 0 1.172-4.892v-.468a7.788 7.788 0 0 0 1.84-1.921 8.142 8.142 0 0 1-2.11.593z"
      ></path>
  </symbol>
  <symbol aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="mail">
    <path  d="M502.3 190.8c3.9-3.1 9.7-.2 9.7 4.7V400c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V195.6c0-5 5.7-7.8 9.7-4.7 22.4 17.4 52.1 39.5 154.1 113.6 21.1 15.4 56.7 47.8 92.2 47.6 35.7.3 72-32.8 92.3-47.6 102-74.1 131.6-96.3 154-113.7zM256 320c23.2.4 56.6-29.2 73.4-41.4 132.7-96.3 142.8-104.7 173.4-128.7 5.8-4.5 9.2-11.5 9.2-18.9v-19c0-26.5-21.5-48-48-48H48C21.5 64 0 85.5 0 112v19c0 7.4 3.4 14.3 9.2 18.9 30.6 23.9 40.7 32.4 173.4 128.7 16.8 12.2 50.2 41.8 73.4 41.4z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="calendar">
    <path d="M452 40h-24V0h-40v40H124V0H84v40H60C26.916 40 0 66.916 0 100v352c0 33.084 26.916 60 60 60h392c33.084 0 60-26.916 60-60V100c0-33.084-26.916-60-60-60zm20 412c0 11.028-8.972 20-20 20H60c-11.028 0-20-8.972-20-20V188h432v264zm0-304H40v-48c0-11.028 8.972-20 20-20h24v40h40V80h264v40h40V80h24c11.028 0 20 8.972 20 20v48z"></path>
    <path d="M76 230h40v40H76zm80 0h40v40h-40zm80 0h40v40h-40zm80 0h40v40h-40zm80 0h40v40h-40zM76 310h40v40H76zm80 0h40v40h-40zm80 0h40v40h-40zm80 0h40v40h-40zM76 390h40v40H76zm80 0h40v40h-40zm80 0h40v40h-40zm80 0h40v40h-40zm80-80h40v40h-40z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="github">
    <path d="M255.968 5.329C114.624 5.329 0 120.401 0 262.353c0 113.536 73.344 209.856 175.104 243.872 12.8 2.368 17.472-5.568 17.472-12.384 0-6.112-.224-22.272-.352-43.712-71.2 15.52-86.24-34.464-86.24-34.464-11.616-29.696-28.416-37.6-28.416-37.6-23.264-15.936 1.728-15.616 1.728-15.616 25.696 1.824 39.2 26.496 39.2 26.496 22.848 39.264 59.936 27.936 74.528 21.344 2.304-16.608 8.928-27.936 16.256-34.368-56.832-6.496-116.608-28.544-116.608-127.008 0-28.064 9.984-51.008 26.368-68.992-2.656-6.496-11.424-32.64 2.496-68 0 0 21.504-6.912 70.4 26.336 20.416-5.696 42.304-8.544 64.096-8.64 21.728.128 43.648 2.944 64.096 8.672 48.864-33.248 70.336-26.336 70.336-26.336 13.952 35.392 5.184 61.504 2.56 68 16.416 17.984 26.304 40.928 26.304 68.992 0 98.72-59.84 120.448-116.864 126.816 9.184 7.936 17.376 23.616 17.376 47.584 0 34.368-.32 62.08-.32 70.496 0 6.88 4.608 14.88 17.6 12.352C438.72 472.145 512 375.857 512 262.353 512 120.401 397.376 5.329 255.968 5.329z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 212 212" id="gitlab">
    <path d="M12.3 74.7h54L43.3 3c-1-3.6-6.4-3.6-7.6 0L12.3 74.8z" />
    <path d="M12.3 74.7L.5 111c-1 3.2 0 6.8 3 8.8l101.6 74-92.5-119z"/>
    <path d="M105 193.7l-38.6-119h-54l92.7 119z"/>
    <path d="M105 193.7l38.7-119H66.4l38.7 119z"/>
    <path d="M105 193.7l38.7-119H198l-93 119z"/>
    <path d="M198 74.7l11.6 36.2c1 3 0 6.6-3 8.6l-101.5 74 93-119z"/>
    <path d="M198 74.7h-54.3L167 3c1.2-3.6 6.4-3.6 7.6 0L198 74.8z"/> 
  </symbol>
  <symbol viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" id="rss">
    <circle cx="3.429" cy="20.571" r="3.429"></circle>
    <path d="M11.429 24h4.57C15.999 15.179 8.821 8.001 0 8v4.572c6.302.001 11.429 5.126 11.429 11.428z"></path>
    <path d="M24 24C24 10.766 13.234 0 0 0v4.571c10.714 0 19.43 8.714 19.43 19.429z"></path>
  </symbol>
  <symbol viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" id="linkedin">
    <path d="M437 0H75C33.648 0 0 33.648 0 75v362c0 41.352 33.648 75 75 75h362c41.352 0 75-33.648 75-75V75c0-41.352-33.648-75-75-75zM181 406h-60V196h60zm0-240h-60v-60h60zm210 240h-60V286c0-16.54-13.46-30-30-30s-30 13.46-30 30v120h-60V196h60v11.309C286.719 202.422 296.93 196 316 196c40.691.043 75 36.547 75 79.688zm0 0"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 612 612" id="arrow">
    <path d="M604.501 440.509L325.398 134.956c-5.331-5.357-12.423-7.627-19.386-7.27-6.989-.357-14.056 1.913-19.387 7.27L7.499 440.509c-9.999 10.024-9.999 26.298 0 36.323s26.223 10.024 36.222 0l262.293-287.164L568.28 476.832c9.999 10.024 26.222 10.024 36.221 0 9.999-10.023 9.999-26.298 0-36.323z"></path>
  </symbol>
  <symbol viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" id="carly">
    <path d="M504.971 239.029L448 182.059V84c0-46.317-37.682-84-84-84h-44c-13.255 0-24 10.745-24 24s10.745 24 24 24h44c19.851 0 36 16.149 36 36v108c0 6.365 2.529 12.47 7.029 16.971L454.059 256l-47.029 47.029A24.002 24.002 0 0 0 400 320v108c0 19.851-16.149 36-36 36h-44c-13.255 0-24 10.745-24 24s10.745 24 24 24h44c46.318 0 84-37.683 84-84v-98.059l56.971-56.971c9.372-9.372 9.372-24.568 0-33.941zM112 192V84c0-19.851 16.149-36 36-36h44c13.255 0 24-10.745 24-24S205.255 0 192 0h-44c-46.318 0-84 37.683-84 84v98.059l-56.971 56.97c-9.373 9.373-9.373 24.568 0 33.941L64 329.941V428c0 46.317 37.682 84 84 84h44c13.255 0 24-10.745 24-24s-10.745-24-24-24h-44c-19.851 0-36-16.149-36-36V320c0-6.365-2.529-12.47-7.029-16.971L57.941 256l47.029-47.029A24.002 24.002 0 0 0 112 192z"></path>
  </symbol>
  <symbol viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" id="copy">
    <path d="M23 2.75A2.75 2.75 0 0 0 20.25 0H8.75A2.75 2.75 0 0 0 6 2.75v13.5A2.75 2.75 0 0 0 8.75 19h11.5A2.75 2.75 0 0 0 23 16.25zM18.25 14.5h-7.5a.75.75 0 0 1 0-1.5h7.5a.75.75 0 0 1 0 1.5zm0-3h-7.5a.75.75 0 0 1 0-1.5h7.5a.75.75 0 0 1 0 1.5zm0-3h-7.5a.75.75 0 0 1 0-1.5h7.5a.75.75 0 0 1 0 1.5z"></path>
    <path d="M8.75 20.5a4.255 4.255 0 0 1-4.25-4.25V2.75c0-.086.02-.166.025-.25H3.75A2.752 2.752 0 0 0 1 5.25v16A2.752 2.752 0 0 0 3.75 24h12a2.752 2.752 0 0 0 2.75-2.75v-.75z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512.001 512.001" id="closeme">
    <path d="M284.286 256.002L506.143 34.144c7.811-7.811 7.811-20.475 0-28.285-7.811-7.81-20.475-7.811-28.285 0L256 227.717 34.143 5.859c-7.811-7.811-20.475-7.811-28.285 0-7.81 7.811-7.811 20.475 0 28.285l221.857 221.857L5.858 477.859c-7.811 7.811-7.811 20.475 0 28.285a19.938 19.938 0 0 0 14.143 5.857 19.94 19.94 0 0 0 14.143-5.857L256 284.287l221.857 221.857c3.905 3.905 9.024 5.857 14.143 5.857s10.237-1.952 14.143-5.857c7.811-7.811 7.811-20.475 0-28.285L284.286 256.002z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="open-menu">
    <path d="M492 236H20c-11.046 0-20 8.954-20 20s8.954 20 20 20h472c11.046 0 20-8.954 20-20s-8.954-20-20-20zm0-160H20C8.954 76 0 84.954 0 96s8.954 20 20 20h472c11.046 0 20-8.954 20-20s-8.954-20-20-20zm0 320H20c-11.046 0-20 8.954-20 20s8.954 20 20 20h472c11.046 0 20-8.954 20-20s-8.954-20-20-20z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="instagram">
    <path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id=youtube>
    <path d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z"/>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="stackoverflow">
    <path d="M21 27v-8h3v11H0V19h3v8h18z"></path><path d="M17.1.2L15 1.8l7.9 10.6 2.1-1.6L17.1.2zm3.7 14.7L10.6 6.4l1.7-2 10.2 8.5-1.7 2zM7.2 12.3l12 5.6 1.1-2.4-12-5.6-1.1 2.4zm-1.8 6.8l13.56 1.96.17-2.38-13.26-2.55-.47 2.97zM19 25H5v-3h14v3z"></path>
  </symbol>
</svg>

<footer class="footer">
  <div class="footer_inner wrap pale">
    <img src='https://alexzshl.gitee.io/blog/icons/apple-touch-icon.png' class="icon icon_2 transparent">
    <p>Copyright<span class="year"></span> ALEXZSHL. All Rights Reserved</p><a class="to_top" href="#documentTop">
  <svg class="icon">
  <use xlink:href="#arrow"></use>
</svg>
</a>

  </div>
</footer>

    <script type="text/javascript" src="https://alexzshl.gitee.io/blog/js/bundle.min.16ce52f0798f54d65cefb0a0fc9228cf99e0b73de57f8a1545fe14259265bf79ba12fe15afd2fd75d5f0bff8f416e8ca8c5c3458f87e014cbfbed8ccfdaee327.js" integrity="sha512-Fs5S8HmPVNZc77Cg/JIoz5ngtz3lf4oVRf4UJZJlv3m6Ev4Vr9L9ddXwv/j0FujKjFw0WPh&#43;AUy/vtjM/a7jJw==" crossorigin="anonymous"></script>
    
  </body>
</html>
